using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections;
using System.Reflection;

namespace MSNClient
{
    public partial class Form_Main : Common_GUI_Data
    {
        public static string Version ="";

        public static string ApplicationName = "MSN Client";

        const int WM_NCHITTEST = 0x84;
        const int HTCLIENT = 0x1;
        const int HTCAPTION = 0x2;
        const int CONTACT_LIST_BORDER = 5;
        // Create a Font object for the node tags.
        Font tagFont = new Font(new FontFamily("Arial"), 8f, FontStyle.Regular);
        Font GroupFont = new Font(new FontFamily("Arial"), 8f, FontStyle.Bold);
        Font MemberFont = new Font(new FontFamily("Arial"), 8f, FontStyle.Regular);
        ArrayList messageForms = new ArrayList();

        ContactList contactList = new ContactList();

        String iLogin = "";
        String iPassword = "";
        bool MSNClientInitializeted = false;
        Thread msnInitializationThread;
        MsnClient msn2;

        public void PrintTime()
        {
            DateTime time = DateTime.Now;
            Console.WriteLine("{0}:{1}:{2}", time.Minute, time.Second, time.Millisecond);
        }
        /*
         * In Separate method because it is takes some time tif it in main form function
         * Better initialize it when it is really neede
         */
        protected void InitializeMsnCleint()
        {
            AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName();
            Version = String.Format("v{0}.{1}a (build {2})", assemblyName.Version.Major, assemblyName.Version.Minor, assemblyName.Version.Build);
            //System.Reflection.Assembly.GetExecutingAssembly()
            msn2 = new MsnClient();
            /*
             * Registering MSN event handlers
             */

            msn2.OnMessageReceiveEvent += new MessageReceiveDelegate(OnMessageReceive);
            msn2.OnContactListReceiveEvent += new ContactListReceiveedDelegate(OnContactListReceiveEvent);
            msn2.OnUserInfoUpdateEvent += new UserInfoUpdateDelegate(OnUserInfoUpdateEvent);
            MSNClientInitializeted = true;
        }
        public Form_Main()
        {
            InitializeComponent();
            //Titlebar Icon
            this.Icon = new Icon(GetType(), "messenger.ico");
            /*
             * Form Initialization
             */
            int width = 20;
            //Calculates size of mine strips
            for (int i = 0; i < menuStrip1.Items.Count; i++)
            {
                width += menuStrip1.Items[i].Size.Width;
            }

            this.ClientSize = new System.Drawing.Size(width - 10, 300);
            this.menuStrip1.Size = new System.Drawing.Size(width, 24);
            this.MinimumSize = new Size(width, 200);


            //Application Text
            this.Text = ApplicationName + " " + Version;

            //Registering events for main window


            /*
             * Other Components
             */
            // ContextMenu for SystrayIcon
            notifyIcon.ContextMenu = new ContextMenu();
            MenuItem showMenuItem = new MenuItem("Show", new EventHandler(showToolStripMenuItem_Click));
            MenuItem exitMenuItem = new MenuItem("Exit", new EventHandler(exitToolStripMenuItem_Click));
            showMenuItem.Name = "showMenuItem";
            showMenuItem.DefaultItem = true;
            notifyIcon.ContextMenu.MenuItems.AddRange(new MenuItem[] { showMenuItem, new MenuItem("-"), exitMenuItem });
            
            /*
             * 
             * Here we are initializating MSNClient Module
             * In Separate thread, because this is not slows main gui thread.
             * 
             */
            msnInitializationThread = new Thread( new ThreadStart(InitializeMsnCleint));
            msnInitializationThread.Start();
            
            contactList.Click += new EventHandler(contactList_Click);
            contactList.DoubleClick += new EventHandler(contactList_DoubleClick);
            /*
             * *Registering contact list events
             */
            Console.WriteLine(String.Format("{0} {1}",ApplicationName,Version));
            Console.WriteLine("Debug Console");

            Controls.Add(contactList);
            contactList.AddGroupNode(GroupTypes.Online);
            contactList.AddGroupNode(GroupTypes.Offline);

            contactList.Nodes[0].Expand();
            SetContactListBounds();

        }

        void contactList_DoubleClick(object sender, EventArgs e)
        {
            ContactList conList = (ContactList)sender;
            if (conList.SelectedNode.Name.Contains("@"))
            {
                MessageForm mf = ShowMessageForm(conList.SelectedNode.Name);
                mf.Text = conList.SelectedNode.Text;
                mf.AccountID = conList.SelectedNode.Name;
            }
        }
        void contactList_Click(object sender, EventArgs e)
        {
            ContactList conlist = (ContactList)sender;
            if (!contactList.SelectedNode.Name.Contains("@"))
            {
                if (contactList.SelectedNode.IsExpanded)
                {
                    contactList.SelectedNode.Collapse();
                }
                else
                {
                    contactList.SelectedNode.Expand();
                }
            }
        }

        void OnUserInfoUpdateEvent(object sender, UserStatusInfo userStatusInfo)
        {
            if (InvokeRequired)
            {
                Invoke(new UserInfoUpdateDelegate(OnUserInfoUpdateEvent), new Object[] { sender, userStatusInfo });
                return;
            }
            if (userStatusInfo.userStatus != UserStatus.Unknown)
            {
                Console.WriteLine("Event:>>" + userStatusInfo.accountName, " (" + userStatusInfo.userStatus + ")");
                if (userStatusInfo.userStatus != UserStatus.Offline)
                {
                    contactList.ChangeMemberGroup(userStatusInfo);
                }
                else
                {
                    contactList.ChangeMemberGroup(userStatusInfo);
                }
            }
            else if (userStatusInfo.accountName != "")
            {
                TreeNode[] nodes = contactList.Nodes.Find(userStatusInfo.accountName, true);
                nodes[0].Tag = userStatusInfo.tagName;
                contactList.Refresh();
            }
        }

        void OnContactListReceiveEvent(object sender, ContactInfo[] users)
        {
            if (InvokeRequired)
            {
                Invoke(new ContactListReceiveedDelegate(OnContactListReceiveEvent), new Object[] { sender, users });
                return;
            }
            this.SystrayIconText(ApplicationName, msn2.currentUserStatus.ToString());
            for (int i = 0; i < users.Length; i++)
            {
                if (users[i].contactType != "Me")
                {
                    contactList.AddMemberNode(users[i], GroupTypes.Offline);
                }
                else
                {
                    this.Text = "<" + users[i].displayName + "> - " + users[i].passportName;
                }
            }
        }
        void OnSendButtonClick(object sender, EventArgs e)
        {

            MessageForm messF = (MessageForm)((Button)sender).FindForm();
            if (messF.GetUserEnteredText != "")
            {
                if (this.msn2.SendData(messF.GetUserEnteredText, messF.AccountID, MsgType.Message))
                {
                    messF.AddMessage(messF.GetUserEnteredText, this.iLogin);
                    messF.ClearUserEneterdText();
                }
                else
                {
                    MessageBox.Show("Can't Sent message");
                }
            }
            else
            {
                MessageBox.Show("Message do not contains any text");
            }
        }
        
        private void OnNudgeButtonClick(object sender, EventArgs e)
        {
            MessageForm messF = (MessageForm) ((ToolStripButton) sender).Owner.FindForm();
            if (this.msn2.SendData(messF.GetUserEnteredText, messF.AccountID, MsgType.Nudge))
            {
                messF.AddMessage("NUDGE", this.iLogin);
            }
            else
            {
                MessageBox.Show("Can't Sent message");
            }
        }


        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            SetContactListBounds();  
        }
        private void SetContactListBounds()
        {
            //In the right side we must to make margin  CONTACT_LIST_BORDER

            int width = this.ClientSize.Width - CONTACT_LIST_BORDER * 2;
            int height = this.ClientSize.Height - CONTACT_LIST_BORDER*2-this.menuStrip1.Height;
            contactList.SetBounds(CONTACT_LIST_BORDER, CONTACT_LIST_BORDER+this.menuStrip1.Height, width, height);
        }
        public void OnMessageReceive(object sender, MessageData message)
        {
            if (InvokeRequired)
            {
                Invoke(new MessageReceiveDelegate(OnMessageReceive), new Object[] { sender, message });
                return;
            }
            MessageForm messF = ShowMessageForm(message.sender);
            if (message.IsOk)
            {
                messF.AccountID = message.sender;
                //Temprorary fix
                messF.Text = message.sender;
                messF.AddMessage(message);
            }
            else
            {
                MessageBox.Show("Message is incorrect!");
            }
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (msn2.IsLoggedIn())
            {
                msn2.LogOut();
            }
            //Preparate for close;
            this.CloseMainForm();
        }
        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Preparate for close;
            this.MakeActive();
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoginForm loginForm = new LoginForm();
            loginForm.AccountName = this.iLogin;
            DialogResult dialogResult = loginForm.ShowDialog();
            if (dialogResult == DialogResult.OK)
            {
                this.iLogin = loginForm.AccountName;
                this.iPassword = loginForm.GetPassword;

                msn2.Login = loginForm.AccountName;
                msn2.Password = loginForm.GetPassword;
                
                msn2.Connect();
            }

        }
        /*
         * File->Disconnect
         */
        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        {   
            contactList.ClearGroups();
            msn2.LogOut();
        }

        /*
         * Tool->Customize
         */
        private void customizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Not implimented in this version!");
        }

        /*
         * Tools->Options
         */
        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Not implimented in this version!");
        }
        public MessageForm ShowMessageForm(String messageFormId)
        {
            MessageForm messF = null;
            for (int i = 0; i < messageForms.Count; i++)
            {
                if (((MessageForm)messageForms[i]).AccountID == messageFormId)
                {
                    messF = (MessageForm)messageForms[i];
                }
                if (((MessageForm)messageForms[i]).IsClosed)
                {
                    messageForms.RemoveAt(i);
                }
            }
            try
            {
                if (messF == null || messF.IsClosed)
                {
                    messF = new MessageForm();
                    messF.RegisterSentButtonClickEvent(new EventHandler(OnSendButtonClick));
                    messF.RegisterNudgeButtonClickEvent(new EventHandler(OnNudgeButtonClick));
                    messF.FormClosed += new FormClosedEventHandler(OnMessageFormClosed);
                    messageForms.Add(messF);
                }
                messF.Show();
                if(messF.WindowState == FormWindowState.Minimized)
                    messF.WindowState = FormWindowState.Normal;
                messF.Activate();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            return messF;
        }

        void OnMessageFormClosed(object sender, FormClosedEventArgs e)
        {
            messageForms.Remove(sender);
            Console.WriteLine("OnCLose"+messageForms.Count);
        }
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_NCHITTEST)
            {
                if ((int)m.Result == HTCLIENT)
                    m.Result = (IntPtr)HTCAPTION;
            }
            
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show(ApplicationName+" "+Version+"\nby Oleg Kuznetsov");
        }
    }
}